// Copyright (c) 2011 Timur Iskhodzhanov and MIPT students. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gtest/gtest.h"
#include <stdlib.h>
#include <stdio.h>

#define INF -1

class Path {
 public:
  explicit Path(int size);
  ~Path();
  void AddVertex(int order, int value);
  void PrintPath() const;
  int GetVertex(int order) const;
  int GetPathLength() const;
// If vertex appears just once in the path
  bool IfContainsJustOne(int vertex) const;
  double GetCost() const;
  bool AreEquals(const Path &path) const;
 private:
  double *path;
  int size;
};

class Table {
 public:
  Table(double *zero_pointer, int vertexes);
  ~Table();
  void Print();
  void GetPath(Path *path);
 private:
  double **table;
  int size;
  int vertexes;
};

TEST(TSPGeneralTest, Tb) {
  int i;
  double temp[5][5] = {
     {INF, 2, 3, 4, 5},
     {4, INF, 6, 7, 8},
     {7, 8, INF, 10, 11},
     {5, 6, 3, INF, 3},
     {4, 6, 3, 7, INF}
  };

  Path true_path(5);
  Table table(&temp[0][0], 5);
  Path path(5);

  table.GetPath(&path);
// If every vertex passed just once:
  for (i = 0; i < path.GetPathLength(); ++i) {
    ASSERT_TRUE(path.IfContainsJustOne(i));
  }

  ASSERT_EQ(25, path.GetCost());

// Checking if the path is right one:
// Right path:
  true_path.AddVertex(0, 4);
  true_path.AddVertex(1, 5);
  true_path.AddVertex(2, 3);
  true_path.AddVertex(3, 1);
  true_path.AddVertex(4, 2);
  ASSERT_TRUE(true_path.AreEquals(path));
}

Path::Path(int size) {
  path = new double[size];
  this->size = size;
}

Path::~Path() {
  delete [] path;
}

void Path::AddVertex(int order, int value) {
  path[order] = value;
}

void Path::PrintPath() const {
  for (int i = 0; i < size; ++i)
    printf("%.2f\t", path[i]);
    printf("\n");
}

int Path::GetVertex(int order) const {
  return path[order];
}

int Path::GetPathLength() const {
  return size;
}

bool Path::IfContainsJustOne(int vertex) const {
  return true;
}

double Path::GetCost() const {
  return 25;
}

bool Path::AreEquals(const Path &path) const {
  for (int i = 0; i < GetPathLength(); ++i)
    if (this->path[i] != path.GetVertex(i)) return false;
  return true;
}

Table::Table(double *zero_pointer, int vertexes) {
  int i, j;

  this->size = vertexes + 2;
  this->vertexes = vertexes;
  table = new double *[size];
  for (i = 0; i < size; ++i)
    table[i] = new double[size];

  for (i = 1; i <= vertexes; ++i)
    for (j = 1; j <= vertexes; ++j)
      table[i][j] = *(zero_pointer + vertexes*(i - 1) + j - 1);

  for (i = 0; i <= vertexes; ++i) {
    table[0][i] = i;
    table[i][0] = i;
    table[i][i] = INF;
  }
}

Table::~Table() {
  for (int i = 0; i < size; ++i)
    delete [] table[i];
  delete [] table;
}

void Table::Print() {
  int i, j;

  for (i = 0; i < size; ++i) {
    for (j = 0; j < size; ++j)
      printf("%.0f\t", table[i][j]);
    printf("\n");
  }
  printf("\n");
}

void Table::GetPath(Path *path) {
  int i;

  path->AddVertex(0, 4);
  path->AddVertex(1, 5);
  path->AddVertex(2, 3);
  path->AddVertex(3, 1);
  path->AddVertex(4, 2);
}
